<?php

# -- DÉBUT NOTE DE LICENCE -------------------------------------
#
# Ce fichier fait partie de Clicpage.
#
# Copyright (c) 2010 Francois (www.clicpage.net)
# Distribué selon les termes de la licence GPL version 2.0.
# Consultez le fichier LICENCE ou
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
#
# -- FIN NOTE DE LICENCE ---------------------------------------

/**
@ingroup CP_DONNEES
@nosubgrouping
@brief Actions sur un média

Une instance de cpMedia représente un média du site.

Ses variables membres permettent d'accéder à toutes les données
du média issues de la base de données.

Ses méthodes permettent, entre autres, d'effectuer les actions suivantes:
- Vérifier le type de fichier
- Obtenir l'URL d'une icône correspondant au type de fichier
- Afficher un aperçu du média
- Générer ou supprimer une miniature
- Envoyer le média au navigateur
- Supprimer le média

*/

class cpMedia
{
	
	
	
	
	
	protected $core;						///< <b>cpCore</b>		Référence à l'objet cpCore de l'application
	
	public $media_id;
	public $media_dossier;
	public $media_fichier;
	public $media_type;
	public $media_titre;
	public $media_description;
	public $media_date_creation;
	public $media_date_modification;
	public $utilisateur_id;
	
	/**
	<b>array</b> Taille des miniatures:
	- m: image moyenne
	- s: petite image (small)
	- t: vignette (thumbnail)
	- sq: carré (square)
	*/
	public $thumb_sizes = array(	
		'm' => array(448,'ratio','medium'),
		's' => array(240,'ratio','small'),
		't' => array(100,'ratio','thumbnail'),
		'ico' => array(64, 'crop', 'icone'),
		'sq' => array(48,'crop','square')
	);
	
	
	
	
	
	/// @name Initialisation et mise à jour des valeurs
	//@{
	
	
	/**
	Initialise une instance de cpMedia.
	
	@param	rs			<b>recordset</b>	Données de la base de données
	@param	core		<b>cpCore</b>		Référence à cpCore
	*/
	public function __construct($rs, $core)
	{
		$this->core =& $core;		
		$this->initRs($rs);	
	}
	
	
	/** @ignore */
	protected function initRs($rs)
	{
		
		$this->media_id = (integer) $rs->media_id;
		$this->media_dossier = $rs->media_dossier;
		$this->media_fichier = $rs->media_fichier;
		$this->media_type = $rs->media_type;
		$this->media_titre = $rs->media_titre;
		$this->media_description = $rs->media_description;
		$this->media_date_creation = $rs->media_date_creation;
		$this->media_date_modification = $rs->media_date_modification;
		$this->utilisateur_id = $rs->utilisateur_id;
		
		# --COMPORTEMENT-- coreInitRsMedia
		$this->core->executerComportement('coreInitRsMedia', $rs, $this);
		
	}
	
	
	/**
	Met à jour les valeurs de cpMedia pour qu'elles
	correspondent à celles de la base de données.
	
	Doit être appelée chaque fois qu'on modifie les données
	du média dans la base de données.
	*/
	public function rafraichir()
	{
		$rs = $this->core->site->getMedias(array('media_id' => $this->media_id), CP_GET_RS);
		$this->initRs($rs);
	}
	//@}

	
	

	
	/// @name Informations sur le média
	//@{
	
	
	/**
	Retourne le chemin absolu permettant d'accéder
	au fichier du média sur le serveur.
	
	@return	<b>string</b>	Chemin absolu du fichier
	*/
	public function cheminFichier()
	{
		return CP_CHEMIN_MEDIAS.$this->media_dossier.'/'.$this->media_fichier;
	}
	
	
	/**
	Retourne l'URL à utiliser pour afficher le média
	sur la partie publique du site.
	
	@param	rel		<b>boolean</b>		Indique si l'URL doit être relative
	
	@return	<b>string</b>	URL relative du média
	*/
	public function publicURL($rel=true)
	{
		if($rel) {
			return path::clean(CP_URL_PUBLIQUE_RELATIVE.'medias'.$this->media_dossier.'/'.$this->media_fichier);
		} else {
			return CP_URL_PUBLIQUE.path::clean('medias'.$this->media_dossier.'/'.$this->media_fichier);
		}
	}
	
	
	/**
	Indique si le média est une image.
	
	@return	<b>boolean</b>
	*/
	public function estImage()
	{
		if(substr($this->media_type, 0, 6) == 'image/') {
			return true;
		}
		return false;
	}
	
	
	/**
	Retourne l'URL d'une icône en lien avec le type de
	média. Utilisable dans l'administration seulement.
	
	@return	<b>string</b>	URL de l'icône
	*/
	public function icone()
	{
		
		if($this->estImage())
		{
			if(function_exists('imagegd2')) {
				return 'media.php?media_id='.(integer) $this->media_id.'&s=ico';
			}
			return 'images/64/icone_image.png';
		}
		
		switch($this->media_type):
		
			case 'application/x-debian-package':
			case 'application/x-gzip':
			case 'application/x-java-archive':
			case 'application/rar':
			case 'application/x-redhat-package-manager':
			case 'application/x-tar':
			case 'application/x-gtar':
			case 'application/zip':
				return 'images/64/icone_archive.png';
			break;
			
			case 'audio/x-aiff':
			case 'audio/basic':
			case 'audio/mpeg3':
			case 'audio/x-midi':
			case 'audio/x-wav':
				return 'images/64/icone_audio.png';
			break;
				
			case 'text/css':
			case 'text/javascript':
			case 'text/html':
				return 'images/64/icone_code.png';
			break;
			
			case 'application/vnd.oasis.opendocument.text':
			case 'application/vnd.sun.xml.writer':
			case 'application/msword':
			case 'application/rtf':
			case 'application/pdf':
			case 'application/postscript':
			case 'text/richtext':
				return 'images/64/icone_document.png';
			break;
			
			case 'application/vnd.oasis.opendocument.presentation':
			case 'application/vnd.sun.xml.impress':
			case 'application/mspowerpoint':
				return 'images/64/icone_slide.png';
			break;
			
			case 'application/vnd.oasis.opendocument.spreadsheet':
			case 'application/vnd.sun.xml.calc':
			case 'application/msexcel':	
				return 'images/64/icone_spreadsheet.png';
			break;
				
			case 'text/plain':
				return 'images/64/icone_texte.png';
			break;
			
			case 'application/ogg':
			case 'application/x-shockwave-flash':
			case 'video/mpeg':
			case 'video/vnd.vivo':
			case 'video/quicktime':
			case 'video/mp4':
			case 'video/x-m4v':
			case 'video/x-flv':
			case 'video/x-msvideo':
				return 'images/64/icone_video.png';
			break;
			
			default:
				return 'images/64/icone_default.png';
			break;
		
		endswitch;

	}
	
	
	/**
	Retourne du code HTML présentant un aperçu du média.
	Utilisable dans l'administration seulement.
	
	@return	<b>string</b>	Code HTML de l'aperçu
	*/
	public function apercu($taille, $admin=true)
	{
		
		if($this->estImage()) {
			return '<img src="media.php?media_id='.(integer) $this->media_id.'&s='.html::escapeHTML($taille).'" '.
				'alt="'.html::escapeHTML($this->media_titre).'"/>';
		}
		
		return '<a href="media.php?media_id='.(integer) $this->media_id.'&download=1">'.__('Télécharger le média').'</a>';
		
	}
	//@}
	
	
	
	
	/// @name Envoi au navigateur
	//@{
	
	
	/**
	Envoi le média au navigateur (header approprié et
	contenu du média). 
	
	@param	taille		<b>string|integer</b>	Taille de l'image a envoyer
	@param	download	<b>boolean</b>			Indique si un header présentant le média
												comme un fichier à télécharger doit être
												envoyé.
	
	@return	<b>string</b>	Chemin absolu du fichier
	*/
	public function afficher($taille=NULL, $download=false)
	{
		
		# Affichage d'une image
		if($this->estImage())
		{
			
			if(!empty($taille) && array_key_exists($taille, $this->thumb_sizes)) {
				$_w = $_h = $this->thumb_sizes[$taille][0];
				$mode = $this->thumb_sizes[$taille][1];
				$preset = true;
			} elseif(!empty($taille) && is_numeric($taille)) {	
				$_w = $_h = (integer) $taille;
				$mode = 'ratio';
				$preset = false;
			}
			
			# Image redimensionnée
			if(!empty($mode))
			{

				try
				{

					$img = new imageTools();
					$img->loadImage($this->cheminFichier());
					
					if($img->getW() > $_w || $img->getH() > $_h)
					{
					
						$thumbFile = path::clean(CP_CHEMIN_MEDIAS.$this->media_dossier.'/.thumb'.$_w.'.'.($mode == 'crop' ? 'crop.' : '').$this->media_fichier.'.jpg');
						
						# Redimensionnement
						if(!file_exists($thumbFile)) {
							
							$img->resize($_w,$_h,$mode);
							
							if($preset)
							{
								$img->output('jpeg', $thumbFile, 80);
							}
							else
							{
								
								# Vérifier si la miniature fait partie d'une page
								$rs = $this->core->con->select('SELECT count(media_id) FROM '.$this->core->prefix.'pages_medias '.
									'WHERE media_id = '.(integer) $this->media_id.' AND page_media_taille = '.(integer) $taille.' LIMIT 1' 
								);
								
								# Si la miniature fait partie d'une page
								if(!$rs->f(0) == 0)
								{

									$img->output('jpeg', $thumbFile, 80);
									
									$cur = $this->core->con->openCursor($this->core->prefix.'pages_medias');
									$cur->page_media_statut = CP_MINIATURE_CREEE;
									$cur->update('WHERE media_id = '.(integer) $this->media_id.' AND page_media_taille = '.(integer) $taille);
	
								}
								# Si la miniature ne fait pas partie d'une page
								else
								{
									http::cache(array($this->cheminFichier()), array(strtotime($this->media_date_modification)));
									$img->output('jpeg');
									exit;
								}						

							}
							
						}
						
						# Affichage de l'image redimensionnée
						http::cache(array($thumbFile, $this->cheminFichier()), array(strtotime($this->media_date_modification)));
						header('Content-Type: image/jpeg');
						header('Content-Length: '.filesize($thumbFile));
						readfile($thumbFile);
						exit;
					
					}

				}
				catch(Exception $e)	{}

			}
			
		}

		# Affichage sans modification
		$this->afficherDirect($download);
		
	}
	
	
	/** @ignore */
	protected function afficherDirect($download=false)
	{
		
		# Headers
		http::cache(array($this->cheminFichier()), array(strtotime($this->media_date_modification)));
		header('Content-Type: '.$this->media_type);
		header('Content-Length: '.filesize($this->cheminFichier()));
		
		if($download) {
			header('Content-Disposition: attachment; filename="'.$this->media_fichier.'"');
		}
		
		# Affichage du fichier
		readfile($this->cheminFichier());
		
	}
	//@}
	
	
	
	
	
	/// @name Gestion des miniatures
	//@{
	
	
	/**
	Tente de générer un fichier de miniature de 
	taille <var>$taille</var>.
	
	@param	taille	<b>string|integer</b>	Taille de la miniature
	@param	mode	<b>boolean</b>			Mode (force, crop, ratio)
	
	@return	<b>boolean</b>	Indique si la miniature a pu être générée correctement
	*/
	public function genererMiniature($taille,$mode='ratio')
	{
		try {
			
			$_w = $_h = (integer) $taille;
			
			$img = new imageTools();
			$img->loadImage($this->cheminFichier());
						
			if($img->getW() > $_w || $img->getH() > $_h)
			{
				$thumbFile = path::clean(CP_CHEMIN_MEDIAS.$this->media_dossier.'/.thumb'.$_w.'.'.$this->media_fichier.'.jpg');
				$img->resize($_w,$_h,$mode);
				$img->output('jpeg', $thumbFile, 80);			
				return true;
			}
			
		} catch(Exception $e) { }
		
		return false;
		
	}
	

	/**
	Supprime toutes les miniatures générées antérieurement
	pour le média.
	*/
	public function supprimerMiniatures()
	{
		$filemanager = new filemanager(CP_CHEMIN_MEDIAS);
		$filemanager->chdir($this->media_dossier);
		$filemanager->getDir();
		
		$pattern = '/^\.thumb([0-9]*)\.'.str_replace('.', '\.', $this->media_fichier).'\.jpg$/';
		
		foreach($filemanager->dir['files'] as $file) {
			if(preg_match($pattern, $file->basename)) {
				$filemanager->removeFile($file->basename);
			}	
		}
	}
	//@}
	
	
	
	
	
	/// @name Actions
	//@{
	
	
	/**
	Modifie les propriétés du média.
		
	@param	cur	<b>cursor</b>	Curseur de média
	*/
	public function enregistrer($cur)
	{
		
		# Le titre du média ne doit pas être vide
		if($cur->isField('media_titre') && $cur->media_titre == '') {
			throw new cpErreur(__('Vous devez indiquer un titre.'), 'media_titre', 101);
		}
		
		$media_fichier = $this->media_fichier;

		# Renommer le fichier?
		if($cur->isField('media_fichier') && $cur->media_fichier != $this->media_fichier) {
			
			# Vérifier la présence de caractères indésirables dans le nom du fichier
			$count = 0;		
			$test = str_replace(array('?','%','&','#','=','+','<','>', '/', '\\'),'',$cur->media_fichier, $count);
			if($count != 0) {
				throw new cpErreur(sprintf(__('Les caractères suivants sont interdits: %s'), '? % & # = + < > / \\'), 'media_fichier', 110);
			}
			
			# Nettoyer le nom du fichier
			$cur->media_fichier = files::tidyFileName($cur->media_fichier);

			# Renommer le fichier
			try {
				$filemanager = new filemanager(CP_CHEMIN_MEDIAS);
				$filemanager->moveFile($this->media_dossier.'/'.$thihs->media_fichier, $this->media_dossier.'/'.$cur->media_fichier);
			} catch(Exception $e) {
				throw new cpErreur(__('Impossible de renommer le fichier.'), 'media_fichier', 199);
			}
			
			$media_fichier = $cur->media_fichier;
			
			# Supprimer les miniatures
			$this->supprimerMiniatures();
			
		}
		
		# Déplacer le fichier?
		if($cur->isField('media_dossier'))
		{
			
			# Vérifier que le dossier de destination existe
			if(!is_dir(CP_CHEMIN_MEDIAS.$cur->media_dossier)) {
				throw new cpErreur(__('Impossible de déplacer le fichier.'), 'media_dossier', 199);
			}
			
			$cur->media_dossier = path::clean($cur->media_dossier);
		
			if(substr($cur->media_dossier, 0, 1) != '/') {
				$cur->media_dossier = '/'.$cur->media_dossier;
			}
			
			# --COMPORTEMENT-- coreAvantDeplacerMedia
			$this->core->executerComportement('coreAvantDeplacerMedia', $cur, $this);
			
			# Déplacer le fichier
			$filemanager = new filemanager(CP_CHEMIN_MEDIAS);
			$filemanager->moveFile($this->media_dossier.'/'.$media_fichier, $cur->media_dossier.'/'.$media_fichier);
			
			# Supprimer les miniatures
			$this->supprimerMiniatures();
			
			# --COMPORTEMENT-- coreApresDeplacerMedia
			$this->core->executerComportement('coreApresDeplacerMedia', $cur, $this);
			
		}
		
		# Date de modification
		$cur->media_date_modification = dt::str('%Y-%m-%d %H:%M:%S');
		
		# --COMPORTEMENT-- coreAvantEnregistrerMedia
		$this->core->executerComportement('coreAvantEnregistrerMedia', $cur, $this);
		
		$cur->update('WHERE media_id = '.(integer) $this->media_id);
		
		# --COMPORTEMENT-- coreApresEnregistrerMedia
		$this->core->executerComportement('coreApresEnregistrerMedia', $cur, $this);
		
		$this->rafraichir();

	}


	/**
	Supprime le média (fichier sur le serveur et enregistrement
	dans la base de données).
	*/
	public function supprimer()
	{

		# --COMPORTEMENT-- coreAvantSupprimerMedia
		$this->core->executerComportement('coreAvantSupprimerMedia', $this);
		
		if(is_file($this->cheminFichier())) {
			$this->supprimerMiniatures();
			$filemanager = new filemanager(CP_CHEMIN_MEDIAS);
			$filemanager->removeFile($this->media_dossier.'/'.$this->media_fichier);
		}
		
		$this->core->con->execute(
			'DELETE FROM '.$this->core->prefix.'medias '.
			'WHERE media_id = '.(integer) $this->media_id
		);
		
		# --COMPORTEMENT-- coreApresSupprimerMedia
		$this->core->executerComportement('coreApresSupprimerMedia', $this);
		
	}
	

	//@}


}

?>